/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//		File Name		:		ObjectManager.cpp
//
//		Author			:		Kevin Jordan
//            
//		Purpose			:		To encapsulate the functions and members of the ObjectManager
//
//		Dates			:		Written( Feb 15, 2011 ) by Kevin Jordan		LastUpdate( Feb 19, 2011  ) by Kevin Jordan 
//	
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "VIN_ObjectManager.h"
#include "CBaseObject.h"
#include "CEnemy.h"
#include <algorithm>
#include "CGamePlayState.h"
using std::sort;

VIN_ObjectManager* VIN_ObjectManager::m_pInstance = NULL;

VIN_ObjectManager::VIN_ObjectManager()
{

	m_pInstance = NULL;
	pPlayer = NULL;

}


VIN_ObjectManager::~VIN_ObjectManager()
{


}

bool VIN_ObjectManager::CheckCollision()
{
	bool check;

	//Check the Enemies to objects
	for(unsigned int i = 0; i < m_vEnemies.size(); i++)
	{
		for(unsigned int j = 0; j< m_vObjects.size(); j++)
		{
			check = m_vEnemies[i]->CheckCollision(m_vObjects[j]);

			if(check)
				continue;
		}
	}

	//Check Player to Objects
	for(unsigned int j = 0; j< m_vObjects.size(); j++)
	{
		check = m_vObjects[j]->CheckCollision(pPlayer);

		if(check)
			continue;
	}

	//Check Player to Enemies
	for(unsigned int k = 0; k < m_vEnemies.size(); k++)
	{
		check = m_vEnemies[k]->CheckCollision(pPlayer);

		if(check)
			continue;
	}
	//Enemy to Player
	for(unsigned int k = 0; k < m_vEnemies.size(); k++)
	{
		if(!m_vEnemies.empty())
			check = pPlayer->CheckCollision(m_vEnemies[k]);

		if(check)
			continue;
	}

	//Check Player to Objects
	for(unsigned int i = 0; i< m_vObjects.size(); i++)
	{
		check = pPlayer->CheckCollision(m_vObjects[i]);

		if(check)
			continue;
	}
	return false;
}


//Loop through every list and Update and Render
void VIN_ObjectManager::UpdateObjects(float fElapsedTime)
{
	vector<CBaseObject*> deadlist;
	
		for (unsigned int i=0; i < m_vEnemies.size(); i++)
		{	
			CBaseObject* Enemy = (CBaseObject*)(m_vEnemies[i]);
			if( !((CBaseEnemy*)Enemy)->GetAlive() )
			{
				deadlist.push_back(Enemy);
				CHubState::GetInstance()->GetPlayer()->SetCash( CHubState::GetInstance()->GetPlayer()->GetCash() + 50 );
				continue;
			}
			m_vEnemies[i]->Update(fElapsedTime);


	}
	for (unsigned int i=0; i < deadlist.size(); i++)
	{
		RemoveObject(0, deadlist[i]);
	}


	//Player's List
	for (unsigned int i=0; i < m_vP_Objects.size(); i++)
		m_vP_Objects[i]->Update(fElapsedTime);

	for (unsigned int i=0; i < m_vObjects.size(); i++)
		m_vObjects[i]->Update(fElapsedTime);

	pPlayer->Update(fElapsedTime);

}

bool VIN_ObjectManager::InputObjects()
{

	if( pPlayer )
	{
		pPlayer->Input();
	}

	return true;
}

bool ZSort( IBaseInterface* obj1, IBaseInterface* obj2 )
{ 

	return obj1->GetPosY() < obj2->GetPosY();
}
void VIN_ObjectManager::RenderObjects(void)
{
	vector<IBaseInterface*> CompiledList;

	for (unsigned int i=0; i < m_vEnemies.size(); i++)
		CompiledList.push_back(m_vEnemies[i]);

	for (unsigned int i=0; i < m_vP_Objects.size(); i++)
		CompiledList.push_back(m_vP_Objects[i]);

	for (unsigned int i=0; i < m_vObjects.size(); i++)
		CompiledList.push_back(m_vObjects[i]);

	CompiledList.push_back(pPlayer);

	sort(CompiledList.begin(), CompiledList.end(), ZSort );

	for( unsigned int j = 0; j < CompiledList.size(); j++ )
	{

		if( CGamePlayState::GetInstance()->GetLose() )
		{
			if( CompiledList[j]->GetType() == OBJ_PLAYER )
			{
				continue;
			}
		}

		if( CGamePlayState::GetInstance()->GetWin() )
		{
			if( CompiledList[j]->GetType() == OBJ_PLAYER )
			{
				continue;
			}
		}
		CompiledList[j]->Render();
	}

}

//check the type then add it to appropriate vector
void VIN_ObjectManager::AddObject(int ListToAdd, IBaseInterface* pObject)
{
	//check the type then add it to appropriate vector
	//Int is which of the lists you wish to add the object to
	// 0 = for Anything Enemy Related, 1 = for Player and Play related Objects, 2 = for any other Object
	//Check to see if object is good
	if( pObject == NULL )
		return;

	switch( ListToAdd )
	{

	case 0:
		{
			m_vEnemies.push_back(pObject);
			pObject->AddRef();
		}
		break;

	case 1:
		{
			m_vP_Objects.push_back(pObject);
			pObject->AddRef();
		}
		break;

	case 2:
		{
			m_vObjects.push_back(pObject);
			pObject->AddRef();
		}
		break;


	}

}
//check the type then remove it from appropriate vector
void VIN_ObjectManager::RemoveObject(int ListToRemove, IBaseInterface* pObject)
{

	//check the type then add it to appropriate vector
	//Int is which of the lists you wish to remove the object from
	// 0 = for Anything Enemy Related, 1 = for Player Projectiles, 2 = for any other Object

	if( pObject == NULL )
		return;

	switch(ListToRemove)
	{

	case 0:
		{
			for(vector<IBaseInterface*>::iterator iter = m_vEnemies.begin(); iter != m_vEnemies.end(); iter++)
			{

				if((*iter) == pObject )
				{
					//Remove my reference to this object.
					(*iter)->Release();

					//Remove the object from the list
					iter = m_vEnemies.erase(iter);
					break;
				}

			}

		}


		break;
	case 1:
		{

			for(vector<IBaseInterface*>::iterator iter = m_vP_Objects.begin(); iter != m_vP_Objects.end(); iter++)
			{

				if((*iter) == pObject )
				{
					//Remove my reference to this object.
					(*iter)->Release();

					//Remove the object from the list
					iter = m_vP_Objects.erase(iter);
					break;
				}


			}

		}
		break;
	case 2:
		{

			for(vector<IBaseInterface*>::iterator iter = m_vObjects.begin(); iter != m_vObjects.end(); iter++)
			{

				if((*iter) == pObject )
				{
					//Remove my reference to this object.
					(*iter)->Release();

					//Remove the object from the list
					iter = m_vObjects.erase(iter);
					break;
				}

			}

		}
		break;
	}





}
void VIN_ObjectManager::KillAll()
{
	for(int i = 0; i < (int)m_vEnemies.size();i++)
	{
		((CBaseEnemy*)m_vEnemies[i])->SetHP( ((CBaseEnemy*)m_vEnemies[i])->GetHP() - 9001);
	}
}


//Remove all Objects from everyList
void VIN_ObjectManager::RemoveAllObjects(void)
{
	//Enemy List
	if( GetNumOfObjectsEnemies() != 0 )
	{
		for( unsigned int i = 0; i < m_vEnemies.size(); i++ )
		{
			m_vEnemies[i]->Release();
		}

		m_vEnemies.clear();
	}

	//Player Projectile List

	if( GetNumOfObjectsPlayerProjectiles() != 0 )
	{
		for( unsigned int i = 0; i < m_vP_Objects.size(); i++ )
		{

			m_vP_Objects[i]->Release();
		}

		m_vP_Objects.clear();
	}



	//Object List
	if( GetNumOfObjects_Object() != 0 )
	{
		for( unsigned int i = 0; i < m_vObjects.size(); i++ )
		{

			m_vObjects[i]->Release();
		}
		m_vObjects.clear();
	}

}

VIN_ObjectManager*	VIN_ObjectManager::GetInstance()
{
	if( !m_pInstance )
	{
		m_pInstance = new VIN_ObjectManager();
	}
	return m_pInstance;
}

void VIN_ObjectManager::DeleteInstance()
{

	if(  m_pInstance )
	{
		delete m_pInstance;
		m_pInstance = NULL;
	}

}


void VIN_ObjectManager::ShutDown()
{
	if( m_pInstance )
	{
		DeleteInstance();
	}
}